"""卖家对话消息相关接口"""

from fastapi import APIRouter, Depends, Request, Body, UploadFile, File, Form
from sqlalchemy.ext.asyncio import AsyncSession
import aiohttp

from config.enums import BusinessType
from config.get_db import get_db
from module_admin.annotation.log_annotation import Log
from module_admin.aspect.interface_auth import CheckUserInterfaceAuth
from module_admin.entity.vo.seller_message_vo import (
    SellerMessageCreateModel,
    SellerMessageQueryModel,
)
from pydantic import BaseModel, Field
from typing import Optional
from module_admin.service.seller_message_service import SellerMessageService
from module_admin.service.login_service import LoginService
from module_admin.entity.vo.user_vo import CurrentUserModel
from utils.log_util import logger
from utils.page_util import PageResponseModel
from utils.response_util import ResponseUtil


sellerMessageController = APIRouter(prefix='/agent/chat', tags=['卖家对话管理'])


class ChatSendRequest(BaseModel):
    """发送聊天消息请求模型"""
    client_id: Optional[str] = None  # ✅ 可选，如果未提供则自动选择分配给当前用户的下单类型agent
    seller_id: str
    item_id: Optional[str] = None
    message: str
    temp_id: Optional[str] = None  # ✅ 标准字段 (snake_case)
    tempId: Optional[str] = None   # ✅ 兼容前端 (camelCase)
    mid: Optional[str] = None      # ✅ 消息ID (用于请求-响应匹配)


class ChatOpenRequest(BaseModel):
    """打开聊天窗口请求模型"""
    client_id: Optional[str] = None  # ✅ 可选，如果未提供则自动选择分配给当前用户的下单类型agent
    seller_id: str
    item_id: Optional[str] = None
    seller_name: Optional[str] = None


class ChatReadRequest(BaseModel):
    """发送已读回执请求模型"""
    client_id: str
    seller_id: str
    item_id: Optional[str] = None
    message_ids: list[str]  # 消息ID列表，格式为 ["3808247424509.PNM", ...]


class ChatRecallRequest(BaseModel):
    """撤回消息请求模型"""
    client_id: str
    seller_id: str
    item_id: Optional[str] = None
    message_id: str  # 要撤回的消息ID，格式为 "3808247424509.PNM"


@sellerMessageController.get(
    '/messages',
    response_model=PageResponseModel,
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:list'))]
)
async def get_seller_messages(
    request: Request,
    query: SellerMessageQueryModel = Depends(SellerMessageQueryModel),
    page_num: int = 1,
    page_size: int = 10,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserModel = Depends(LoginService.get_current_user)
):
    """分页获取卖家对话消息（支持权限过滤：非管理员只能看到分配给自己的agent的聊天记录）"""

    try:
        # 判断是否是管理员（role_id=1的超级管理员）
        role_id_list = [role.role_id for role in current_user.user.role]
        is_admin = 1 in role_id_list
        
        result = await SellerMessageService.get_message_list(
            db=db,
            query_params=query,
            page_num=page_num,
            page_size=page_size,
            current_user_id=current_user.user.user_id,
            is_admin=is_admin
        )
        return ResponseUtil.success(data=result)
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/messages',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:add'))]
)
@Log(title='卖家对话消息', business_type=BusinessType.INSERT)
async def create_seller_message(
    request: Request,
    body: SellerMessageCreateModel,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserModel = Depends(LoginService.get_current_user)
):
    """创建卖家对话消息（用于手动补录或调试）"""

    try:
        message = await SellerMessageService.create_message(
            db=db,
            data=body.model_dump(),
            create_by=current_user.user.user_id,
            dept_id=current_user.user.dept_id
        )
        await db.commit()
        return ResponseUtil.success(msg='创建成功', data=message)
    except Exception as exc:
        await db.rollback()
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.delete(
    '/messages/{message_id}',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:remove'))]
)
@Log(title='卖家对话消息', business_type=BusinessType.DELETE)
async def delete_seller_message(
    request: Request,
    message_id: int,
    db: AsyncSession = Depends(get_db)
):
    """删除卖家对话消息"""

    try:
        await SellerMessageService.delete_message(db, message_id)
        await db.commit()
        return ResponseUtil.success(msg='删除成功')
    except Exception as exc:
        await db.rollback()
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/clean_duplicates',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:list'))]
)
async def clean_duplicate_sessions(
    request: Request,
    db: AsyncSession = Depends(get_db)
):
    """
    【手动修复】清理重复会话（合并同Item同Seller的会话）
    """
    try:
        from module_admin.dao.seller_conversation_dao import SellerConversationDao
        result = await SellerConversationDao.merge_all_duplicates(db)
        return ResponseUtil.success(data=result, msg="清理完成")
    except Exception as e:
        logger.exception(e)
        return ResponseUtil.error(msg=str(e))


@sellerMessageController.get(
    '/sessions',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:list'))]
)
async def get_chat_sessions(
    request: Request,
    client_id: str = None,
    force_refresh: bool = False,  # ✅ 是否强制刷新（忽略缓存）
    limit: int = 20,  # ✅ 每次加载数量
    cursor: str = None,  # ✅ 游标：上一页最后一条的last_message_time（ISO格式）
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserModel = Depends(LoginService.get_current_user)
):
    """
    获取聊天会话列表（优化版：从seller_conversation表查询）
    
    性能提升：
    - 查询时间从 >10秒 降低到 <100ms
    - 去除复杂的子查询和UNION ALL
    - 直接从seller_conversation表获取完整会话信息
    """
    try:
        # 判断是否是管理员（role_id=1的超级管理员）
        role_id_list = [role.role_id for role in current_user.user.role]
        is_admin = 1 in role_id_list
        
        # ⚠️ 权限过滤：非管理员只能看到分配给自己的agent的聊天记录
        allowed_client_ids = None
        if not is_admin:
            from module_admin.entity.do.client_do import AgentClient
            from sqlalchemy import select
            # 查询分配给当前用户的所有agent的client_id列表（1对1分配）
            agent_query = select(AgentClient.client_id).where(
                AgentClient.del_flag == '0',
                AgentClient.assigned_user_id == current_user.user.user_id
            )
            agent_result = await db.execute(agent_query)
            allowed_client_ids = [row[0] for row in agent_result.all()]
            
            # 如果指定了client_id，检查权限
            if client_id and client_id not in allowed_client_ids:
                return ResponseUtil.success(data={'sessions': [], 'total': 0})
            
            # 如果没有分配任何agent，返回空
            if not allowed_client_ids:
                return ResponseUtil.success(data={'sessions': [], 'total': 0})
        
        from module_admin.entity.do.seller_conversation_do import SellerConversation
        from sqlalchemy import select, desc
        
        # ✅ 简单高效的查询：直接从seller_conversation表获取
        # ⚠️ 只查询有item_id的会话（过滤掉系统会话和无效会话）
        stmt = select(SellerConversation).where(
            SellerConversation.del_flag == '0',
            SellerConversation.item_id.isnot(None),
            SellerConversation.item_id != ''
        )
        
        # 权限过滤
        if not is_admin and allowed_client_ids:
            stmt = stmt.where(SellerConversation.client_id.in_(allowed_client_ids))
        
        # client_id过滤
        if client_id:
            stmt = stmt.where(SellerConversation.client_id == client_id)
        
        # ✅ 游标分页：如果有cursor，只查询时间早于cursor的数据
        import asyncio
        if cursor:
            try:
                from datetime import datetime
                cursor_time = datetime.fromisoformat(cursor)
                stmt = stmt.where(SellerConversation.last_message_time < cursor_time)
                logger.debug(f"使用游标分页，cursor={cursor}")
            except Exception as e:
                logger.warning(f"游标解析失败，忽略: {e}")
        
        # 按最后消息时间倒序排序
        stmt = stmt.order_by(desc(SellerConversation.last_message_time))
        
        # ✅ 限制返回数量（多查1条用于判断是否还有更多）
        stmt = stmt.limit(limit + 1)
        
        # 执行查询
        result = await db.execute(stmt)
        conversations = result.scalars().all()
        
        # 判断是否还有更多数据
        has_more = len(conversations) > limit
        if has_more:
            conversations = conversations[:limit]  # 移除多查的那一条
        
        logger.info(f"[会话列表] 查询到 {len(conversations)} 个会话，has_more={has_more}")
        
        # 构建响应数据（通过匿名API获取实时商品和卖家信息）
        sessions = []
        
        # ✅ 并发处理优化：第一步 - 并发获取API数据（不操作数据库）
        async def fetch_api_data(conv):
            result = {
                'conv': conv,
                'api_data': None,
                'item_status': conv.item_status if hasattr(conv, 'item_status') else None,
                'needs_db_update': False
            }
            
            # 优先从数据库读取扩展信息（JSON字段）
            import json
            try:
                if hasattr(conv, 'item_tags') and conv.item_tags:
                    json.loads(conv.item_tags)
                if hasattr(conv, 'item_images') and conv.item_images:
                    json.loads(conv.item_images)
                if hasattr(conv, 'video_info') and conv.video_info:
                    json.loads(conv.video_info)
            except json.JSONDecodeError:
                pass
            
            # 判断是否需要刷新API
            from datetime import datetime, timedelta
            needs_api_fetch = False
            
            # 用户主动刷新
            if force_refresh and conv.item_id:
                needs_api_fetch = True
            elif conv.item_id:
                # 策略1：缺少关键信息
                if not conv.item_title or not conv.item_image:
                    needs_api_fetch = True
                # 策略2：图片列表缓存过期（24小时）
                elif not (hasattr(conv, 'item_images') and conv.item_images) and not (hasattr(conv, 'video_info') and conv.video_info):
                    if not hasattr(conv, 'item_info_updated_at') or not conv.item_info_updated_at:
                        needs_api_fetch = True
                    else:
                        age = datetime.now() - conv.item_info_updated_at
                        if age > timedelta(hours=24):
                            needs_api_fetch = True
                # 策略3：关键信息定期刷新（5分钟）
                else:
                    if hasattr(conv, 'item_info_updated_at') and conv.item_info_updated_at:
                        age = datetime.now() - conv.item_info_updated_at
                        if age > timedelta(minutes=5):
                            needs_api_fetch = True
                    else:
                        needs_api_fetch = True
            
            if needs_api_fetch:
                try:
                    from module_admin.service.goofish_anonymous_service import GoofishAnonymousService
                    redis = request.app.state.redis
                    
                    # ✅ 关键修改：只要需要更新，就强制不使用缓存，确保获取到最新的商品状态（如已下架）
                    # 之前因为使用了缓存，导致下架状态更新不及时
                    item_info = await GoofishAnonymousService.get_item_and_seller_info(
                        redis, 
                        int(conv.item_id), 
                        use_cache=False
                    )
                    
                    if item_info:
                        result['api_data'] = item_info
                        result['needs_db_update'] = True
                    else:
                        # 商品已下架
                        result['item_status'] = 'deleted'
                        result['needs_db_update'] = True
                except Exception as e:
                    logger.warning(f"⚠️ 会话 {conv.conversation_id}: API获取失败: {e}")
                    result['item_status'] = 'deleted'
            
            return result

        # 执行并发API请求
        try:
            api_tasks = [fetch_api_data(conv) for conv in conversations]
            # 注意：这里只并发网络请求，不涉及数据库操作
            processed_results = await asyncio.gather(*api_tasks, return_exceptions=True)
        except Exception as e:
            logger.error(f"❌ 并发API请求失败: {e}")
            processed_results = []

        # ✅ 第二步：串行处理数据库更新和结果构建
        sessions = []
        import json
        
        for res in processed_results:
            if isinstance(res, Exception):
                logger.error(f"处理会话异常: {res}")
                continue
                
            conv = res['conv']
            
            # ✅ 关键修复：在任何 potential commit 之前，提前提取所有对象属性
            # 否则一旦 commit，对象就会 expired，再次访问会触发隐式 IO 导致 MissingGreenlet 错误
            conv_data = {
                'conversation_id': conv.conversation_id,
                'chat_id': conv.chat_id,
                'client_id': conv.client_id,
                'seller_id': conv.seller_id,
                'seller_name': conv.seller_name,
                'seller_avatar': conv.seller_avatar,
                'item_id': conv.item_id,
                'item_title': conv.item_title,
                'item_image': conv.item_image,
                'item_price': conv.item_price,
                'last_message': conv.last_message,
                'last_message_time': conv.last_message_time,
                'last_message_direction': conv.last_message_direction,
                'unread_count': conv.unread_count or 0,
                'item_status': conv.item_status if hasattr(conv, 'item_status') else 0,
                'item_status_str': conv.item_status_str if hasattr(conv, 'item_status_str') else None
            }
            
            api_data = res['api_data']
            needs_db_update = res['needs_db_update']
            
            # 准备基础数据（使用提取的数据）
            seller_name = conv_data['seller_name']
            seller_avatar = conv_data['seller_avatar']
            item_title = conv_data['item_title']
            item_image = conv_data['item_image']
            item_price = conv_data['item_price']
            item_status = res.get('item_status') # 从API结果获取的新状态
            item_status_str = conv_data['item_status_str']
            
            # 如果API没有返回状态，使用数据库中的状态
            if item_status is None:
                item_status = conv_data['item_status']
            
            # ✅ 修复类型错误：将 'deleted' 转换为整数 -2
            if item_status == 'deleted':
                item_status = -2
            
            item_tags = []
            item_images = []
            video_info = None
            
            # 解析原有JSON（尝试从数据库字段解析，如果之前没解析成功）
            # 注意：这里 conv.item_tags 等大字段可能也需要提前加载，但一般 Text 字段默认随对象加载
            try:
                if hasattr(conv, 'item_tags') and conv.item_tags:
                    item_tags = json.loads(conv.item_tags)
                if hasattr(conv, 'item_images') and conv.item_images:
                    item_images = json.loads(conv.item_images)
                if hasattr(conv, 'video_info') and conv.video_info:
                    video_info = json.loads(conv.video_info)
            except:
                pass
            
            # 如果有新API数据，更新变量
            if api_data:
                if api_data.get('seller_name'): seller_name = api_data['seller_name']
                if api_data.get('seller_avatar'): seller_avatar = api_data['seller_avatar']
                if api_data.get('item_title'): item_title = api_data['item_title']
                if api_data.get('item_image'): item_image = api_data['item_image']
                if api_data.get('item_price'): item_price = api_data['item_price']
                if api_data.get('item_tags'): item_tags = api_data['item_tags']
                if api_data.get('image_infos'): item_images = api_data['image_infos']
                if api_data.get('video_play_info'): video_info = api_data['video_play_info']
                if api_data.get('item_status') is not None:
                    val = api_data['item_status']
                    if val == 'deleted':
                        item_status = -2
                    else:
                        item_status = val
                    item_status_str = api_data.get('item_status_str', '')
            
            # ✅ 串行更新数据库（使用同一个Session，安全）
            if needs_db_update:
                try:
                    from module_admin.dao.seller_conversation_dao import SellerConversationDao
                    item_tags_json = json.dumps(item_tags, ensure_ascii=False) if item_tags else None
                    item_images_json = json.dumps(item_images, ensure_ascii=False) if item_images else None
                    video_info_json = json.dumps(video_info, ensure_ascii=False) if video_info else None
                    
                    await SellerConversationDao.create_or_update_conversation(
                        db=db,
                        client_id=conv_data['client_id'],
                        conversation_id=conv_data['conversation_id'],
                        item_id=conv_data['item_id'],
                        item_title=item_title,
                        item_image=item_image,
                        item_price=item_price,
                        item_tags=item_tags_json,
                        item_images=item_images_json,
                        video_info=video_info_json,
                        item_status=item_status,
                        item_status_str=item_status_str,
                        seller_name=seller_name,
                        seller_avatar=seller_avatar,
                    )
                    # 注意：这里不立即commit，等所有更新完成后统一commit，或者逐个commit
                    # 为了安全起见，逐个commit防止一个失败影响所有
                    await db.commit()
                except Exception as update_error:
                    await db.rollback()
                    logger.error(f"❌ 更新数据库商品信息失败: {update_error}")
            
            # ✅ 最终兜底：如果seller_name还是空，尝试从历史消息中获取（串行查询）
            if not seller_name:
                try:
                    from module_admin.entity.do.seller_message_do import SellerMessage
                    from sqlalchemy import select
                    
                    msg_stmt = select(SellerMessage.seller_name).where(
                        SellerMessage.conversation_id == conv_data['conversation_id'],
                        SellerMessage.seller_name.isnot(None),
                        SellerMessage.seller_name != '',
                        SellerMessage.del_flag == '0'
                    ).limit(1)
                    
                    msg_result = await db.execute(msg_stmt)
                    msg_seller_name = msg_result.scalar_one_or_none()
                    
                    if msg_seller_name:
                        seller_name = msg_seller_name
                    else:
                        seller_name = '未知卖家'
                except Exception as e:
                    seller_name = '未知卖家'
            
            # 构建返回对象（使用提取的数据变量）
            sessions.append({
                'conversation_id': conv_data['conversation_id'],
                'chat_id': conv_data['chat_id'],
                'client_id': conv_data['client_id'],
                'seller_id': conv_data['seller_id'],
                'seller_name': seller_name,
                'seller_avatar': seller_avatar,
                'item_id': conv_data['item_id'],
                'item_title': item_title,
                'item_image': item_image,
                'item_price': item_price,
                'item_tags': item_tags,
                'image_infos': item_images,
                'video_play_info': video_info,
                'item_status': item_status if item_status is not None else 0,
                'item_status_str': item_status_str,
                'last_message': conv_data['last_message'],
                'last_message_time': conv_data['last_message_time'].isoformat() if conv_data['last_message_time'] else None,
                'last_message_direction': conv_data['last_message_direction'],
                'unread_count': conv_data['unread_count']
            })
            
        logger.info(f"✅ [会话列表] 处理完成，返回 {len(sessions)} 个会话")
        
        # ✅ 返回游标分页信息
        next_cursor = None
        if sessions and has_more:
            # 使用最后一条的last_message_time作为下次请求的cursor
            last_session = sessions[-1]
            next_cursor = last_session.get('last_message_time')
        
        return ResponseUtil.success(data={
            'sessions': sessions,
            'has_more': has_more,
            'next_cursor': next_cursor,  # 下次请求传这个值
            'count': len(sessions)
        })
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=f"查询会话列表失败: {str(exc)}")


        subq_system = (
            select(
                SellerMessage.conversation_id,
                func.max(SellerMessage.message_time).label('max_time')
            )
            .where(
                SellerMessage.del_flag == '0',
                SellerMessage.direction == 'system'  # ✅ 系统消息（如"会话已开启"）
            )
        )
        
        # ⚠️ 权限过滤：非管理员只能看到分配给自己的agent的聊天记录
        if not is_admin and allowed_client_ids:
            subq_system = subq_system.where(SellerMessage.client_id.in_(allowed_client_ids))
        
        if client_id:
            subq_system = subq_system.where(SellerMessage.client_id == client_id)
        
        # ✅ 排除已有接收消息或发送消息的会话（避免重复）
        subq_system = subq_system.where(
            ~SellerMessage.conversation_id.in_(
                select(subq_recv.c.conversation_id)
            )
        )
        subq_system = subq_system.where(
            ~SellerMessage.conversation_id.in_(
                select(subq_send.c.conversation_id)
            )
        )
        
        subq_system = subq_system.group_by(SellerMessage.conversation_id).subquery()
        
        # 第四步：合并三个子查询（使用UNION ALL）
        from sqlalchemy import union_all
        subq_union = union_all(
            select(subq_recv.c.conversation_id, subq_recv.c.max_time),
            select(subq_send.c.conversation_id, subq_send.c.max_time),
            select(subq_system.c.conversation_id, subq_system.c.max_time)
        ).subquery()
        
        # 主查询：获取每个会话的最新消息
        # ✅ 如果指定了client_id，只查询该client_id的消息；否则查询所有client_id的消息
        stmt = (
            select(SellerMessage)
            .join(
                subq_union,
                (SellerMessage.conversation_id == subq_union.c.conversation_id) &
                (SellerMessage.message_time == subq_union.c.max_time)
            )
        )
        
        # ⚠️ 权限过滤：非管理员只能看到分配给自己的agent的聊天记录
        if not is_admin and allowed_client_ids:
            stmt = stmt.where(SellerMessage.client_id.in_(allowed_client_ids))
        
        # ✅ 如果指定了client_id，添加client_id过滤；否则不过滤，以便跨client_id去重
        if client_id:
            stmt = stmt.where(SellerMessage.client_id == client_id)
        
        stmt = stmt.order_by(desc(SellerMessage.message_time))
        
        result = await db.execute(stmt)
        messages = result.scalars().all()
        
        # ✅ 调试日志：打印查询结果
        logger.info(f"[会话列表] 查询到 {len(messages)} 条消息")
        for i, msg in enumerate(messages[:5]):  # 只打印前5条
            logger.info(f"[会话列表] 消息{i+1}: conversation_id={msg.conversation_id}, seller_id={msg.seller_id}, message_id={msg.message_id}, message_type={msg.message_type}, direction={msg.direction}, message_time={msg.message_time}, client_id={msg.client_id}")
        
        # ✅ 过滤掉conversation_id等于seller_id的错误数据（这些是错误存储的数据）
        # ⚠️ 注意：修复应该在消息保存时进行（tcp_server.py），这里只过滤错误数据
        valid_messages = []
        error_count = 0
        for msg in messages:
            # ✅ 检查conversation_id是否等于seller_id（这是错误的数据）
            if msg.conversation_id and msg.seller_id and str(msg.conversation_id) == str(msg.seller_id):
                error_count += 1
                logger.warning(f"[会话列表] ⚠️ 检测到错误的conversation_id（等于seller_id）: conversation_id={msg.conversation_id}, seller_id={msg.seller_id}, item_id={msg.item_id}, message_id={msg.message_id}")
                # ⚠️ 跳过这条错误的消息（修复应该在消息保存时进行，确保conversation_id正确构建）
                continue
            else:
                # conversation_id正常，保留
                valid_messages.append(msg)
        
        messages = valid_messages
        if error_count > 0:
            logger.warning(f"[会话列表] ⚠️ 过滤了 {error_count} 条conversation_id等于seller_id的错误消息")
        logger.info(f"[会话列表] 过滤错误数据后剩余 {len(messages)} 条消息")
        
        # ✅ 按conversation_id去重，只保留每个conversation_id的最新消息（避免发送端和接收端创建重复会话）
        # 使用字典存储，key为conversation_id，value为消息对象
        # ✅ 重要：如果指定了client_id，则只保留该client_id的消息；否则跨client_id去重
        sessions_dict = {}
        for msg in messages:
            conversation_id = msg.conversation_id
            
            # ✅ 如果指定了client_id，确保消息的client_id匹配（双重检查，防止查询返回错误数据）
            if client_id and msg.client_id != client_id:
                logger.warning(f"[会话列表] ⚠️ 检测到错误的client_id（与过滤条件不匹配）: msg.client_id={msg.client_id}, filter_client_id={client_id}")
                continue
            
            # ✅ 如果该conversation_id已存在，比较消息时间，保留最新的
            if conversation_id in sessions_dict:
                existing_msg = sessions_dict[conversation_id]
                # 如果当前消息更新，替换
                if msg.message_time > existing_msg.message_time:
                    sessions_dict[conversation_id] = msg
            else:
                sessions_dict[conversation_id] = msg
        
        # ✅ 将字典转换为列表，按消息时间倒序排序
        messages = list(sessions_dict.values())
        messages.sort(key=lambda x: x.message_time, reverse=True)
        
        # ✅ 重要：对于每个conversation_id，应该只返回一个会话
        # 如果同一个conversation_id中有不同的seller_id（可能是send和recv方向不同），
        # 优先使用接收消息（direction='recv'）的seller_id，因为这是真正的卖家ID
        conversation_dict = {}
        for msg in messages:
            conversation_id = msg.conversation_id
            existing_msg = conversation_dict.get(conversation_id)
            
            if not existing_msg:
                # 如果不存在，直接添加
                conversation_dict[conversation_id] = msg
            else:
                # 如果已存在，优先使用接收消息的seller_id（这是真正的卖家）
                # 如果都是发送消息或都是接收消息，使用时间最新的
                existing_is_recv = existing_msg.direction == 'recv'
                current_is_recv = msg.direction == 'recv'
                
                if current_is_recv and not existing_is_recv:
                    # 当前消息是接收消息，优先使用（seller_id是正确的）
                    conversation_dict[conversation_id] = msg
                elif not current_is_recv and existing_is_recv:
                    # 已存在的消息是接收消息，保留已存在的
                    pass
                elif msg.message_time > existing_msg.message_time:
                    # 如果方向相同，使用时间最新的
                    conversation_dict[conversation_id] = msg
        
        # ✅ 将去重后的结果转换回列表
        messages = list(conversation_dict.values())
        messages.sort(key=lambda x: x.message_time, reverse=True)
        
        # ✅ 再次去重：如果存在相同sellerId和itemId但不同conversation_id的会话，只保留chat_id格式的（不包含#号）
        # 这种情况可能发生在conversation_id从seller_id#item_id格式更新为chat_id格式时
        seller_item_dict = {}
        for msg in messages:
            if not msg.seller_id or not msg.item_id:
                # 如果没有seller_id或item_id，跳过（这种情况不应该出现）
                continue
            
            key = f"{msg.seller_id}#{msg.item_id}"
            existing_msg = seller_item_dict.get(key)
            
            if not existing_msg:
                # 如果不存在，直接添加
                seller_item_dict[key] = msg
            else:
                # 如果已存在，优先使用chat_id格式的conversation_id（不包含#号）
                existing_is_chat_id = '#' not in existing_msg.conversation_id
                current_is_chat_id = '#' not in msg.conversation_id
                
                if current_is_chat_id and not existing_is_chat_id:
                    # 当前会话使用chat_id格式，优先使用
                    seller_item_dict[key] = msg
                elif not current_is_chat_id and existing_is_chat_id:
                    # 已存在的会话使用chat_id格式，保留已存在的
                    pass
                elif msg.message_time > existing_msg.message_time:
                    # 如果格式相同，使用时间最新的
                    seller_item_dict[key] = msg
        
        # ✅ 将去重后的结果转换回列表
        messages = list(seller_item_dict.values())
        messages.sort(key=lambda x: x.message_time, reverse=True)
        
        # ✅ 调试日志：打印去重后的会话
        logger.info(f"[会话列表] 去重后有 {len(messages)} 个会话")
        for i, msg in enumerate(messages):
            logger.info(f"[会话列表] 会话{i+1}: conversation_id={msg.conversation_id}, seller_id={msg.seller_id}, item_id={msg.item_id}, message_type={msg.message_type}, direction={msg.direction}")
        
        # 构建会话列表
        sessions = []
        for msg in messages:
            # ✅ 如果是系统消息，查找该会话的最后一条非系统消息
            last_message = msg.message_content
            last_message_type_display = msg.message_type  # 用于前端特殊显示
            
            if msg.message_type == 'system' or msg.direction == 'system':
                # 查找该会话的最后一条非系统消息
                from sqlalchemy import select
                last_real_msg = await db.execute(
                    select(SellerMessage)
                    .where(
                        SellerMessage.conversation_id == msg.conversation_id,
                        SellerMessage.client_id == msg.client_id,
                        SellerMessage.del_flag == '0',
                        SellerMessage.message_type != 'system',
                        SellerMessage.direction != 'system'
                    )
                    .order_by(SellerMessage.message_time.desc())
                    .limit(1)
                )
                last_real_msg = last_real_msg.scalar_one_or_none()
                if last_real_msg:
                    last_message = last_real_msg.message_content
                    last_message_type_display = last_real_msg.message_type
                else:
                    # ✅ system消息特殊显示
                    last_message = '点击查看会话' if msg.message_content == '会话已开启' else msg.message_content
                    last_message_type_display = 'system'
            
            # ✅ 修复：解码HTML实体编码（如 &#x8BF7; -> 请）
            if last_message:
                import html
                last_message = html.unescape(last_message)
            
            # ✅ 根据消息类型设置显示文本
            if last_message_type_display == 'image':
                last_message_display = '[图片]'
            elif last_message_type_display == 'voice':
                last_message_display = '[语音]'
            elif last_message_type_display == 'video':
                last_message_display = '[视频]'
            elif last_message_type_display == 'system':
                last_message_display = f'[系统消息] {last_message}'
            else:
                last_message_display = last_message
            
            # ✅ 如果item_id存在但没有商品信息，尝试通过匿名请求获取
            item_price = None
            item_image = None
            item_tags = []
            seller_avatar = None
            item_status = None  # ✅ 商品状态
            # ✅ 初始化变量，使用数据库中的值作为默认值（后备）
            final_seller_name = msg.seller_name or '未知卖家'
            
            if msg.item_id:
                try:
                    from module_admin.service.goofish_anonymous_service import GoofishAnonymousService
                    redis = request.app.state.redis
                    
                    item_info = await GoofishAnonymousService.get_item_and_seller_info(redis, int(msg.item_id))
                    # ✅ 判断商品信息是否有效（不为None且包含关键字段）
                    if item_info and (item_info.get('item_price') or item_info.get('item_image') or item_info.get('seller_name')):
                        item_price = item_info.get('item_price')
                        item_image = item_info.get('item_image')
                        item_tags = item_info.get('item_tags', [])
                        seller_avatar = item_info.get('seller_avatar')
                        # ✅ 提取商品状态（0=在线, 1=已卖掉）
                        if item_info.get('item_status') is not None:
                            item_status = item_info.get('item_status')
                        # ✅ 修复：始终优先使用API返回的seller_name，只有当API没有返回时才使用数据库中的值
                        # 这样可以修正数据库中可能存在的错误seller_name
                        if item_info.get('seller_name'):
                            final_seller_name = item_info['seller_name']
                            logger.debug(f"✅ 会话列表：使用API的seller_name: {final_seller_name} (conversation_id={msg.conversation_id})")
                        else:
                            logger.debug(f"⚠️ 会话列表：API未返回seller_name，使用数据库值: {final_seller_name} (conversation_id={msg.conversation_id})")
                    else:
                        # ✅ 商品信息获取失败或为空，标记为已下架
                        item_status = 'deleted'
                        logger.warning(f"⚠️ 会话列表：商品已下架或删除: item_id={msg.item_id}, item_info={item_info} (conversation_id={msg.conversation_id})")
                except Exception as e:
                    logger.warning(f"⚠️ 会话列表：获取商品信息异常: item_id={msg.item_id}, error={e}")
                    # ✅ 获取失败也标记为已下架
                    item_status = 'deleted'
            
            session_data = {
                'conversation_id': msg.conversation_id,
                'seller_id': msg.seller_id,
                'seller_name': final_seller_name,  # ✅ 使用可能已更新的seller_name
                'seller_avatar': seller_avatar,  # ✅ 使用从API获取的avatar
                'item_id': msg.item_id,
                'item_title': msg.item_title,
                'item_price': item_price,  # ✅ 使用从API获取的价格
                'item_image': item_image,  # ✅ 使用从API获取的图片
                'item_tags': item_tags,  # ✅ 使用从API获取的标签
                'client_id': msg.client_id,
                'last_message': last_message_display,  # ✅ 使用格式化后的消息（包含类型标签）
                'last_message_raw': last_message,  # ✅ 原始消息内容
                'last_message_time': msg.message_time.isoformat() if msg.message_time else None,
                'last_message_type': last_message_type_display,  # ✅ 实际显示的消息类型
                'last_direction': msg.direction
            }
            
            # ✅ 添加商品状态（如果存在）：0=在线, 1=已卖掉, 'deleted'=已下架
            # 确保item_status字段始终存在，避免前端undefined错误
            session_data['item_status'] = item_status if item_status is not None else 0  # 默认为在线状态
            
            # ✅ 查询黑名单状态
            # 注意：这里需要通过Agent查询，暂时先标记为False，后续通过Agent异步查询
            # TODO: 实现批量查询黑名单状态以提升性能
            session_data['is_blocked'] = False  # 默认未拉黑
            
            sessions.append(session_data)
        
        return ResponseUtil.success(data={'sessions': sessions, 'total': len(sessions)})
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/open',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:open'))]
)
async def open_chat(
    request: Request,
    body: ChatOpenRequest = Body(...),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserModel = Depends(LoginService.get_current_user)
):
    """打开聊天窗口（使用匿名请求获取商品详情和卖家信息，避免Agent风控）"""
    try:
        if not body.seller_id:
            return ResponseUtil.error(msg='缺少 seller_id')
        
        # ✅ 如果提供了 item_id，使用匿名请求获取商品和卖家信息（避免Agent风控）
        item_info = None
        seller_info = None
        
        if body.item_id:
            try:
                from module_admin.service.goofish_anonymous_service import GoofishAnonymousService
                redis = request.app.state.redis
                
                # 使用匿名请求获取商品和卖家信息
                # ✅ 强制不使用缓存，确保打开聊天时看到的是最新的商品状态（如已下架）
                item_info = await GoofishAnonymousService.get_item_and_seller_info(
                    redis, 
                    int(body.item_id),
                    use_cache=False
                )
                
                if item_info:
                    # 更新 seller_name 和 seller_id（使用从API获取的纯数字ID）
                    if item_info.get('seller_id'):
                        body.seller_id = str(item_info['seller_id'])
                    if item_info.get('seller_name'):
                        body.seller_name = item_info['seller_name']
                    
                    logger.info(f"✅ 通过匿名请求获取商品信息成功: itemId={body.item_id}, sellerId={item_info.get('seller_id')}")
                else:
                    logger.warning(f"⚠️ 匿名请求获取商品信息失败，将使用提供的seller_id: {body.seller_id}")
                    # ✅ 标记商品状态异常（可能已下架或删除），确保包含完整字段避免前端undefined错误
                    item_info = {
                        'item_status': 'deleted', 
                        'error': '商品已下架或删除',
                        'seller_id': body.seller_id,
                        'seller_name': body.seller_name or '未知卖家',
                        'item_title': None,
                        'item_price': None,
                        'item_image': None,
                        'item_tags': [],
                        'seller_avatar': None
                    }
            except Exception as e:
                logger.exception(f"匿名请求获取商品信息时出错: {e}")
                # 出错不影响主流程，继续使用提供的seller_id
        
        # ✅ 先检查是否已有该会话的真实消息记录（使用chat_id作为conversation_id）
        # 优先查找使用chat_id作为conversation_id的消息（真实消息）
        from sqlalchemy import select, or_
        from module_admin.entity.do.seller_message_do import SellerMessage
        
        # 查找该seller_id和item_id的所有消息（可能使用chat_id或seller_id#item_id作为conversation_id）
        fallback_conversation_id = f"{body.seller_id}#{body.item_id or ''}"
        
        # 先查找是否有使用chat_id作为conversation_id的消息（真实消息）
        # chat_id格式通常是纯数字，不包含#号
        existing_real_msg = await db.execute(
            select(SellerMessage).where(
                SellerMessage.seller_id == body.seller_id,
                SellerMessage.item_id == body.item_id,
                SellerMessage.client_id == body.client_id,
                SellerMessage.del_flag == '0',
                ~SellerMessage.conversation_id.like('%#%')  # conversation_id不包含#号，说明是chat_id格式
            ).order_by(SellerMessage.message_time.desc()).limit(1)
        )
        existing_real_msg = existing_real_msg.scalar_one_or_none()
        
        # 如果找到了真实消息，使用它的conversation_id（chat_id）
        if existing_real_msg:
            conversation_id = existing_real_msg.conversation_id
            logger.info(f"✅ 找到已有会话记录，使用chat_id作为conversation_id: {conversation_id}")
        else:
            # 如果没有真实消息，检查是否有使用seller_id#item_id格式的系统消息
            existing_system_msg = await db.execute(
                select(SellerMessage).where(
                    SellerMessage.conversation_id == fallback_conversation_id,
                    SellerMessage.client_id == body.client_id,
                    SellerMessage.del_flag == '0'
                ).limit(1)
            )
            existing_system_msg = existing_system_msg.scalar_one_or_none()
            
            if existing_system_msg:
                # 如果已有系统消息，使用它的conversation_id
                conversation_id = existing_system_msg.conversation_id
                logger.info(f"✅ 找到已有系统消息记录，使用conversation_id: {conversation_id}")
            else:
                # 如果没有消息记录，使用fallback格式（后续真实消息会更新为chat_id）
                conversation_id = fallback_conversation_id
                logger.info(f"⚠️ 未找到已有会话记录，使用fallback格式: {conversation_id}")
        
        # 如果没有消息记录，创建一个初始会话记录（系统消息）
        # ✅ 标记为临时会话，当Agent推送真实消息时会自动更新conversation_id
        if not existing_real_msg and not existing_system_msg:
            from datetime import datetime
            from module_admin.service.seller_message_service import SellerMessageService
            
            # ✅ 如果未提供client_id，自动选择分配给当前用户的下单类型agent
            if not body.client_id:
                from module_admin.service.agent_client_service import AgentClientService
                current_user_id = current_user.user.user_id
                order_clients = await AgentClientService.get_available_order_clients(
                    db, 
                    allow_search_accounts=False,  # 只使用下单类型agent
                    user_id=current_user_id  # ✅ 只选择分配给当前用户的agent
                )
                if order_clients:
                    body.client_id = order_clients[0].client_id
                    logger.info(f"✅ 自动选择下单类型agent: {body.client_id} (user_id={current_user_id})")
                else:
                    return ResponseUtil.error(msg='没有可用的下单类型Agent客户端（请确保已分配并登录）')
            
            # 创建初始会话记录（创建一个系统消息，标识会话已开启）
            # ✅ 使用item_info中的seller_name（如果获取成功），否则使用body中的seller_name
            final_seller_name = None
            if item_info and item_info.get('seller_name'):
                final_seller_name = item_info['seller_name']
            elif body.seller_name:
                final_seller_name = body.seller_name
            else:
                final_seller_name = '未知卖家'
            
            initial_message_data = {
                'conversation_id': conversation_id,  # ✅ 使用fallback格式，后续会更新为真实的chat_id
                'message_id': f"sys_{int(datetime.now().timestamp() * 1000)}",
                'client_id': body.client_id,
                'seller_id': body.seller_id,  # 使用更新后的纯数字seller_id（如果item_info存在）
                'seller_name': final_seller_name,  # ✅ 使用优先级的seller_name
                'item_id': body.item_id,
                'item_title': item_info.get('item_title') if item_info else None,  # 匿名请求获取的商品标题
                'message_type': 'system',
                'direction': 'system',
                'message_content': '会话已开启',
                'message_time': datetime.now()
            }
            
            await SellerMessageService.create_message(
                db=db,
                data=initial_message_data,
                create_by=0,
                dept_id=0
            )
            await db.commit()
            logger.info(f"✅ 已创建初始会话记录（临时conversation_id）: {conversation_id}, client_id={body.client_id}")
        
        # ✅ 不再发送chat_open命令给Agent，让前端决定是否发送
        # 这样避免重复发送，也避免后端发送加密的seller_id
        
        # 返回响应，包含从匿名请求获取的商品信息（确保seller_id是纯数字）
        # ✅ 确定最终的seller_name（优先级：item_info > body.seller_name > '未知卖家'）
        final_seller_name = None
        if item_info and item_info.get('seller_name'):
            final_seller_name = item_info['seller_name']
        elif body.seller_name:
            final_seller_name = body.seller_name
        else:
            final_seller_name = '未知卖家'
        
        response_data = {
            'client_id': body.client_id,
            'seller_id': body.seller_id,  # 使用更新后的纯数字seller_id（如果item_info存在）
            'seller_name': final_seller_name,  # ✅ 使用优先级的seller_name
            'item_id': body.item_id,
            'conversation_id': conversation_id,  # ✅ 返回conversation_id（可能包含chat_id）
        }
        
        # 如果成功获取了商品信息，添加到响应中
        if item_info:
            response_data.update({
                'item_title': item_info.get('item_title'),
                'item_price': item_info.get('item_price'),
                'item_image': item_info.get('item_image'),
                'item_tags': item_info.get('item_tags', []),
                'seller_avatar': item_info.get('seller_avatar'),
                # ✅ 新增：返回完整的图片列表和视频信息
                'image_infos': item_info.get('image_infos', []),
                'video_play_info': item_info.get('video_play_info'),
            })
            # ✅ 确保返回的seller_id是纯数字（从item_info获取）
            if item_info.get('seller_id'):
                response_data['seller_id'] = str(item_info['seller_id'])
            # ✅ 确保返回的seller_name是item_info中的（如果存在）
            if item_info.get('seller_name'):
                response_data['seller_name'] = item_info['seller_name']
            # ✅ 添加商品状态（如果存在）：0=在线, 1=已卖掉, 'deleted'=已下架
            if item_info.get('item_status') is not None:
                response_data['item_status'] = item_info['item_status']
                response_data['item_status_str'] = item_info.get('item_status_str', '')
                # 如果是已下架状态，添加错误信息
                if item_info.get('item_status') == 'deleted':
                    response_data['item_error'] = item_info.get('error', '商品已下架或删除')
            
            # ✅ 新增：保存完整的商品详情到 seller_conversation 表
            try:
                from module_admin.dao.seller_conversation_dao import SellerConversationDao
                import json
                
                # 准备商品详情JSON
                item_tags_json = json.dumps(item_info.get('item_tags', []), ensure_ascii=False) if item_info.get('item_tags') else None
                item_images_json = json.dumps(item_info.get('image_infos', []), ensure_ascii=False) if item_info.get('image_infos') else None
                video_info_json = json.dumps(item_info.get('video_play_info'), ensure_ascii=False) if item_info.get('video_play_info') else None
                
                await SellerConversationDao.create_or_update_conversation(
                    db=db,
                    client_id=body.client_id,
                    conversation_id=conversation_id,
                    chat_id=None,  # 初始没有chat_id
                    seller_id=response_data['seller_id'],
                    seller_name=response_data['seller_name'],
                    seller_avatar=item_info.get('seller_avatar'),
                    item_id=body.item_id,
                    item_title=item_info.get('item_title'),
                    item_image=item_info.get('item_image'),
                    item_price=item_info.get('item_price'),
                    # ✅ 保存扩展信息
                    item_tags=item_tags_json,
                    item_images=item_images_json,
                    video_info=video_info_json,
                    item_status=item_info.get('item_status'),
                    item_status_str=item_info.get('item_status_str'),
                )
                await db.commit()
                logger.info(f"✅ 已保存完整商品详情到seller_conversation表: item_id={body.item_id}")
            except Exception as e:
                logger.error(f"❌ 保存商品详情到seller_conversation表失败: {e}")
                # 不影响主流程
        
        logger.info(f"✅ 已创建会话记录: client_id={body.client_id}, seller_id={response_data['seller_id']}, item_id={body.item_id}")
        return ResponseUtil.success(msg='会话已创建', data=response_data)
        
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/send',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:send'))]
)
async def send_chat_message(
    request: Request,
    body: ChatSendRequest = Body(...),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserModel = Depends(LoginService.get_current_user)
):
    """发送聊天消息（转发到Agent）"""

    try:
        if not body.message or not body.message.strip():
            return ResponseUtil.error(msg='消息内容不能为空')
        
        # ✅ 如果未提供client_id，自动选择分配给当前用户的下单类型agent
        if not body.client_id:
            from module_admin.service.agent_client_service import AgentClientService
            current_user_id = current_user.user.user_id
            order_clients = await AgentClientService.get_available_order_clients(
                db, 
                allow_search_accounts=False,  # 只使用下单类型agent
                user_id=current_user_id  # ✅ 只选择分配给当前用户的agent
            )
            if order_clients:
                body.client_id = order_clients[0].client_id
                logger.info(f"✅ 自动选择下单类型agent: {body.client_id} (user_id={current_user_id})")
            else:
                return ResponseUtil.error(msg='没有可用的下单类型Agent客户端（请确保已分配并登录）')
        
        # 使用TCP客户端管理器发送命令
        from tcp_server.tcp_clients import ClientManager
        import uuid
        
        # ✅ 调试日志
        logger.info(f"📩 [send_chat_message] 收到发送请求: mid={body.mid}, temp_id={body.temp_id or body.tempId}, message={body.message[:20]}...")

        # 构建命令消息
        cmd_message = {
            'event': 'chat_send',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'seller_id': body.seller_id,
                'item_id': body.item_id,
                'message': body.message.strip(),
                'temp_id': body.temp_id or body.tempId,  # ✅ 兼容两种命名风格
                'mid': body.mid  # ✅ 传递消息ID
            },
            'req_id': str(uuid.uuid4())
        }
        
        # 发送到 Agent
        success = await ClientManager.send_to_client(body.client_id, cmd_message)
        
        if success:
            logger.info(f"✅ 已发送聊天消息到 Agent: client_id={body.client_id}, seller_id={body.seller_id}")
            return ResponseUtil.success(msg='消息已发送')
        else:
            return ResponseUtil.error(msg=f'客户端 {body.client_id} 未连接或发送失败')
        
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/read',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:send'))]
)
async def mark_chat_read(
    request: Request,
    body: ChatReadRequest = Body(...),
    db: AsyncSession = Depends(get_db)
):
    """
    发送已读回执（标记消息为已读）
    ⚠️ 只对接收的消息（direction='recv'）发送已读回执，过滤系统消息和自己发送的消息
    """
    try:
        from tcp_server.tcp_clients import ClientManager
        import uuid
        from sqlalchemy import select, and_
        from module_admin.entity.do.seller_message_do import SellerMessage
        
        # ✅ 如果message_ids为空，直接返回
        if not body.message_ids:
            logger.warning(f"⚠️ 已读回执：message_ids为空，跳过发送: client_id={body.client_id}, seller_id={body.seller_id}")
            return ResponseUtil.success(data={"message": "无需发送已读回执", "message_count": 0})
        
        # ✅ 从数据库查询这些消息，过滤出需要发送已读回执的消息
        query = select(SellerMessage).where(
            and_(
                SellerMessage.message_id.in_(body.message_ids),
                SellerMessage.client_id == body.client_id,
                SellerMessage.del_flag == '0',
                # ✅ 只对接收的消息发送已读回执
                SellerMessage.direction == 'recv',
                # ✅ 排除系统消息
                SellerMessage.message_type != 'system'
            )
        )
        result = await db.execute(query)
        valid_messages = result.scalars().all()
        
        # ✅ 提取有效的message_id
        valid_message_ids = [msg.message_id for msg in valid_messages]
        
        # ✅ 如果没有有效消息，直接返回
        if not valid_message_ids:
            logger.info(f"✅ 已读回执：所有消息都已过滤（系统消息或自己发送的消息），无需发送: client_id={body.client_id}, seller_id={body.seller_id}, total={len(body.message_ids)}")
            return ResponseUtil.success(data={"message": "无需发送已读回执（已过滤系统消息和自己发送的消息）", "message_count": 0})
        
        # ✅ 构建已读回执命令消息
        cmd_message = {
            'event': 'chat_read',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'seller_id': body.seller_id,
                'item_id': body.item_id,
                'message_ids': valid_message_ids  # ✅ 只发送过滤后的有效message_id
            },
            'req_id': str(uuid.uuid4())
        }
        
        # ✅ 转发已读回执命令到Agent
        success = await ClientManager.send_to_client(body.client_id, cmd_message)
        
        if success:
            logger.info(f"✅ 已发送已读回执到 Agent: client_id={body.client_id}, seller_id={body.seller_id}, message_count={len(valid_message_ids)} (过滤前: {len(body.message_ids)})")
            return ResponseUtil.success(data={"message": "已读回执已发送", "message_count": len(valid_message_ids)})
        else:
            return ResponseUtil.error(msg="客户端不在线或命令发送失败")
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/recall',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:recall'))]
)
async def recall_chat_message(
    request: Request,
    body: ChatRecallRequest = Body(...)
):
    """
    撤回消息
    """
    try:
        from tcp_server.tcp_clients import ClientManager
        import uuid
        
        # ✅ 构建撤回消息命令
        cmd_message = {
            'event': 'chat_recall',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'seller_id': body.seller_id,
                'item_id': body.item_id,
                'message_id': body.message_id
            },
            'req_id': str(uuid.uuid4())
        }
        
        # ✅ 转发撤回消息命令到Agent
        success = await ClientManager.send_to_client(body.client_id, cmd_message)
        
        if success:
            logger.info(f"✅ 已发送撤回消息命令到 Agent: client_id={body.client_id}, seller_id={body.seller_id}, message_id={body.message_id}")
            return ResponseUtil.success(data={"message": "撤回消息命令已发送", "message_id": body.message_id})
        else:
            return ResponseUtil.error(msg="客户端不在线或命令发送失败")
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.get(
    '/item/{item_id}',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:list'))]
)
async def get_item_info(
    request: Request,
    item_id: int
):
    """获取商品详情（使用匿名请求，避免Agent风控）"""
    try:
        from module_admin.service.goofish_anonymous_service import GoofishAnonymousService
        redis = request.app.state.redis
        
        # 使用匿名请求获取商品和卖家信息
        item_info = await GoofishAnonymousService.get_item_and_seller_info(redis, item_id)
        
        if item_info:
            return ResponseUtil.success(data=item_info)
        else:
            return ResponseUtil.error(msg='获取商品信息失败')
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=str(exc))


@sellerMessageController.post(
    '/upload_image',
    dependencies=[Depends(CheckUserInterfaceAuth('agent:chat:send'))]
)
async def upload_image(
    request: Request,
    file: UploadFile = File(...),
    conversation_id: str = Form(...),  # ✅ 从FormData获取conversation_id
    seller_id: Optional[str] = Form(None),  # ✅ 可选：seller_id（备用）
    item_id: Optional[str] = Form(None),  # ✅ 可选：item_id（备用）
    temp_id: Optional[str] = Form(None),  # ✅ 消息状态机：前端生成的临时ID
    mid: Optional[str] = Form(None),  # ✅ 消息状态机：消息mid
    current_user: CurrentUserModel = Depends(LoginService.get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    上传图片到闲鱼服务器（通过Agent上传，保持IP和Cookie一致性，避免跨IP使用session的风险）
    """
    try:
        # ✅ 从查询参数获取client_id（必须提供）
        client_id = request.query_params.get('client_id')
        if not client_id:
            return ResponseUtil.error(msg='缺少client_id参数，无法通过Agent上传图片')
        
        if not conversation_id:
            return ResponseUtil.error(msg='缺少conversation_id参数，无法关联会话')
        
        # ✅ 解析conversation_id格式：
        # 1. 如果包含#号，格式为{seller_id}#{item_id}
        # 2. 如果不包含#号，可能是chat_id（纯数字），需要从数据库查找对应的seller_id和item_id
        parsed_seller_id = None
        parsed_item_id = None
        is_chat_id_format = False
        
        try:
            if '#' in conversation_id:
                # 格式：{seller_id}#{item_id}
                parts = conversation_id.split('#', 1)
                parsed_seller_id = parts[0] if parts[0] else None
                parsed_item_id = parts[1] if len(parts) > 1 and parts[1] else None
            elif conversation_id and conversation_id.isdigit():
                # 格式：chat_id（纯数字），需要从数据库查找
                is_chat_id_format = True
                from sqlalchemy import select
                from module_admin.entity.do.seller_message_do import SellerMessage
                existing_msg = await db.execute(
                    select(SellerMessage)
                    .where(
                        SellerMessage.conversation_id == conversation_id,
                        SellerMessage.client_id == client_id,
                        SellerMessage.del_flag == '0'
                    )
                    .order_by(SellerMessage.message_time.desc())
                    .limit(1)
                )
                existing_msg = existing_msg.scalar_one_or_none()
                if existing_msg:
                    parsed_seller_id = existing_msg.seller_id
                    parsed_item_id = existing_msg.item_id
                    logger.info(f"✅ 从数据库查找chat_id对应的seller_id和item_id: conversation_id={conversation_id}, seller_id={parsed_seller_id}, item_id={parsed_item_id}")
        except Exception as e:
            logger.warning(f"解析conversation_id失败: {e}, conversation_id={conversation_id}")
        
        # ✅ 优先使用解析出的seller_id和item_id，如果没有则使用Form参数
        final_seller_id = parsed_seller_id or seller_id
        final_item_id = parsed_item_id or item_id
        
        # ✅ 获取user_id用于审计日志
        user_id = current_user.user.user_id if current_user and current_user.user else None
        logger.info(f"📤 用户 {user_id} 上传图片: client_id={client_id}, conversation_id={conversation_id}, seller_id={final_seller_id}, item_id={final_item_id}")
        
        # ✅ 读取上传的文件内容（不压缩，保持原始质量）
        file_content = await file.read()
        file_name = file.filename or 'pasteImg0'
        file_size = len(file_content)
        
        # ✅ 限制图片大小（50MB，使用文件传输服务器，不阻塞TCP）
        MAX_IMAGE_SIZE = 50 * 1024 * 1024  # 50MB
        if file_size > MAX_IMAGE_SIZE:
            return ResponseUtil.error(msg=f'图片大小超过限制（最大{MAX_IMAGE_SIZE // 1024 // 1024}MB），当前{file_size // 1024 // 1024}MB')
        
        logger.info(f"准备上传图片: 大小={file_size}字节, 文件名={file_name}")
        
        # ✅ 获取Agent的IP地址（Agent反向连接到控制端，所以ip_address是Agent的IP）
        from tcp_server.tcp_clients import ClientManager
        client = ClientManager.get_client_by_id(client_id)
        if not client:
            return ResponseUtil.error(msg=f'客户端 {client_id} 未连接')
        
        agent_ip = client.ip_address
        agent_file_receiver_port = 9002  # Agent文件接收服务器端口（从Agent配置获取，默认9002）
        
        logger.info(f"✅ Agent IP: {agent_ip}, 文件接收服务器端口: {agent_file_receiver_port}")
        
        # ✅ 直接POST文件到Agent的文件接收服务器
        import aiohttp
        
        # 构建FormData
        form_data = aiohttp.FormData()
        form_data.add_field('file', 
                          file_content,
                          filename=file_name,
                          content_type=file.content_type or 'image/png')
        
        # ✅ 上传到Agent的文件接收服务器
        agent_file_receiver_url = f"http://{agent_ip}:{agent_file_receiver_port}/upload"
        
        async with aiohttp.ClientSession() as session:
            async with session.post(agent_file_receiver_url, data=form_data) as response:
                if response.status != 200:
                    error_text = await response.text()
                    logger.error(f"文件上传到Agent失败: status={response.status}, error={error_text}")
                    return ResponseUtil.error(msg=f'文件上传失败: HTTP {response.status}')
                
                upload_result = await response.json()
                file_id = upload_result.get('file_id')
                
                if not file_id:
                    return ResponseUtil.error(msg='文件上传失败：未获取到文件ID')
        
        logger.info(f"✅ 文件已上传到Agent: file_id={file_id}")
        
        # ✅ 通过TCP命令通知Agent使用本地文件上传到闲鱼
        import uuid
        
        # ✅ 构建上传命令消息（包含文件ID和会话关联信息）
        cmd_message = {
            'event': 'chat_upload_image',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'file_id': file_id,
                'file_name': file_name,
                'file_size': file_size,
                'conversation_id': conversation_id,  # ✅ 会话ID
                'seller_id': final_seller_id,  # ✅ 卖家ID（从conversation_id解析）
                'item_id': final_item_id,  # ✅ 商品ID（从conversation_id解析）
                'temp_id': temp_id,  # ✅ 消息状态机：前端生成的临时ID
                'mid': mid  # ✅ 消息状态机：消息mid
            },
            'req_id': str(uuid.uuid4())
        }
        
        # ✅ 记录文件上传审计日志
        logger.info(f"📝 文件上传审计: user_id={user_id}, client_id={client_id}, conversation_id={conversation_id}, seller_id={final_seller_id}, item_id={final_item_id}, file_name={file_name}, file_size={file_size}字节, temp_id={temp_id}, mid={mid}")
        
        # ✅ 发送到Agent（Agent会从本地文件读取，然后上传到闲鱼）
        success = await ClientManager.send_to_client(client_id, cmd_message)
        
        if not success:
            logger.error(f"发送上传命令失败: client_id={client_id}")
            return ResponseUtil.error(msg=f'客户端 {client_id} 未连接或发送失败')
        
        logger.info(f"✅ 图片上传命令已发送到Agent: client_id={client_id}, req_id={cmd_message['req_id']}, file_id={file_id}")
        return ResponseUtil.success(data={
            'req_id': cmd_message['req_id'],
            'file_id': file_id,
            'message': '图片上传命令已发送，请等待Agent响应'
        })
                    
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=f'上传失败: {str(exc)}')


@sellerMessageController.post("/hide")
async def hide_conversation(request: Request, data: dict):
    """
    隐藏会话（调用官方WebSocket hide接口）
    
    Args:
        client_id: 客户端ID
        conversation_id: 会话ID
    
    Returns:
        成功/失败响应
    """
    try:
        client_id = data.get('client_id')
        conversation_id = data.get('conversation_id')
        
        if not client_id or not conversation_id:
            return ResponseUtil.error(msg='缺少必要参数')
        
        # 使用TCP客户端管理器发送命令
        from tcp_server.tcp_clients import ClientManager
        import uuid
        
        # 构建命令消息
        cmd_message = {
            'event': 'chat_hide_conversation',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'conversation_id': conversation_id
            },
            'req_id': str(uuid.uuid4())
        }
        
        # 发送到TCP客户端
        success = await ClientManager.send_to_client(client_id, cmd_message)
        
        if not success:
            logger.warning(f"⚠️ 隐藏会话失败: client_id={client_id}, conversation_id={conversation_id}")
            return ResponseUtil.error(msg='发送隐藏命令失败')
        
        logger.info(f"✅ 会话已隐藏: client_id={client_id}, conversation_id={conversation_id}")
        return ResponseUtil.success(msg='会话已隐藏')
        
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=f'隐藏会话失败: {str(exc)}')


@sellerMessageController.post("/block")
async def block_user(request: Request, data: dict):
    """
    加入黑名单（调用官方HTTP API）
    
    Args:
        client_id: 客户端ID
        conversation_id: 会话ID（从conversation_id中提取sessionId）
    
    Returns:
        成功/失败响应
    
    API说明:
        - 查询黑名单: mtop.taobao.idlemessage.pc.blacklist.query
        - 添加黑名单: mtop.taobao.idlemessage.pc.blacklist.add
        - 参数: sessionId (从conversation_id中提取，如 "55659170628@goofish" -> "55659170628")
    """
    try:
        client_id = data.get('client_id')
        conversation_id = data.get('conversation_id')
        
        if not client_id or not conversation_id:
            return ResponseUtil.error(msg='缺少必要参数')
        
        # 从conversation_id中提取sessionId (如 "55659170628@goofish" -> "55659170628")
        session_id = conversation_id.split('@')[0] if '@' in conversation_id else conversation_id
        
        # 发送命令给Agent
        from tcp_server.tcp_clients import ClientManager
        import uuid
        
        cmd_message = {
            'event': 'add_blacklist',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'session_id': session_id
            },
            'req_id': str(uuid.uuid4())
        }
        
        # 发送到TCP客户端
        success = await ClientManager.send_to_client(client_id, cmd_message)
        
        if not success:
            logger.warning(f"⚠️ 加入黑名单失败: client_id={client_id}, session_id={session_id}")
            return ResponseUtil.error(msg='发送黑名单命令失败')
        
        logger.info(f"✅ 已加入黑名单: client_id={client_id}, session_id={session_id}")
        return ResponseUtil.success(msg='已加入黑名单')
        
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=f'加入黑名单失败: {str(exc)}')


@sellerMessageController.post("/unblock")
async def unblock_user(request: Request, data: dict):
    """
    移除黑名单（调用官方HTTP API）
    
    Args:
        client_id: 客户端ID
        conversation_id: 会话ID（从conversation_id中提取sessionId）
    
    Returns:
        成功/失败响应
    
    API说明:
        - 移除黑名单: mtop.taobao.idlemessage.pc.blacklist.remove
        - 参数: sessionId (从conversation_id中提取，如 "55659170628@goofish" -> "55659170628")
    """
    try:
        client_id = data.get('client_id')
        conversation_id = data.get('conversation_id')
        
        if not client_id or not conversation_id:
            return ResponseUtil.error(msg='缺少必要参数')
        
        # 从conversation_id中提取sessionId (如 "55659170628@goofish" -> "55659170628")
        session_id = conversation_id.split('@')[0] if '@' in conversation_id else conversation_id
        
        # 发送命令给Agent
        from tcp_server.tcp_clients import ClientManager
        import uuid
        
        cmd_message = {
            'event': 'remove_blacklist',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {
                'session_id': session_id
            },
            'req_id': str(uuid.uuid4())
        }

        # 发送到TCP客户端
        success = await ClientManager.send_to_client(client_id, cmd_message)
        
        if not success:
            logger.warning(f"⚠️ 移除黑名单失败: client_id={client_id}, session_id={session_id}")
            return ResponseUtil.error(msg='发送移除黑名单命令失败')
        
        logger.info(f"✅ 已移除黑名单: client_id={client_id}, session_id={session_id}")
        return ResponseUtil.success(msg='已移除黑名单')
        
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=f'移除黑名单失败: {str(exc)}')


@sellerMessageController.get("/emoji/list")
async def get_emoji_list(
    request: Request,
    force_refresh: bool = False,
    current_user: CurrentUserModel = Depends(LoginService.get_current_user)
):
    """
    获取表情包列表（IM初始化时调用）
    
    Args:
        force_refresh: 是否强制刷新缓存（默认False）
    
    Returns:
        表情包列表数据
    """
    try:
        import json
        from utils.redis_util import get_redis_connection
        from tcp_server.tcp_clients import client_manager
        import uuid
        
        redis_client = get_redis_connection()
        cache_key = "goofish:emoji_list"
        cache_ttl = 7 * 24 * 3600  # 7天
        
        # 1. 检查Redis缓存
        if not force_refresh:
            cached_data = redis_client.get(cache_key)
            if cached_data:
                try:
                    data = json.loads(cached_data)
                    logger.info(f"✅ 从Redis缓存返回表情包数据（{len(data.get('items', []))}个表情）")
                    return ResponseUtil.success(data={'emoji_data': data, 'from_cache': True})
                except Exception as e:
                    logger.warning(f"解析Redis缓存失败: {e}，重新请求")
        
        # 2. 选择一个可用的Agent（在线、已登录、无异常）
        available_client = None
        all_clients = client_manager.get_all_clients()
        
        for client in all_clients:
            status_data = getattr(client, 'status_data', {})
            is_online = client.status == "connected"
            is_logged_in = status_data.get('login_status') == 'logged_in'
            work_status = status_data.get('work_status', '')
            is_normal = work_status not in ['error', 'banned']
            
            if is_online and is_logged_in and is_normal:
                available_client = client
                logger.info(f"✅ 找到可用Agent: {client.client_id}")
                break
        
        if not available_client:
            return ResponseUtil.error(msg='没有可用的Agent客户端', code=503)
        
        # 3. 发送命令给Agent
        from tcp_server.tcp_clients import ClientManager
        
        cmd_message = {
            'event': 'load_emoji_list',
            'direction': 'req',
            'success': True,
            'code': 0,
            'msg': '',
            'data': {},
            'req_id': str(uuid.uuid4())
        }
        
        logger.info(f"发送命令到Agent {available_client.client_id}: {cmd_message}")
        
        # TODO: 这里需要等待Agent响应，目前简化为直接发送
        # 实际应该使用异步等待机制获取响应
        success = await ClientManager.send_to_client(available_client.client_id, cmd_message)
        
        if not success:
            return ResponseUtil.error(msg='Agent未响应', code=500)
        
        # 注意：当前实现是简化版，实际需要等待Agent的响应
        # 完整实现需要在TCP通信层添加请求-响应匹配机制
        
        return ResponseUtil.success(msg='表情包请求已发送，请从Redis缓存获取或等待Agent响应')
        
    except Exception as exc:
        logger.exception(exc)
        return ResponseUtil.error(msg=f'获取表情包失败: {str(exc)}')
